package cn.ilikes.tools.nosql.jpa.clients;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.hadoop.hbase.client.Result;
import org.slf4j.Logger;

import cn.ilikes.tools.logs.Loggerfactory;
import cn.ilikes.tools.nosql.jpa.JPASQLPersistenUnitEnv;
import cn.ilikes.tools.nosql.jpa.JPASQLRunTimeException;
import cn.ilikes.tools.nosql.jpa.SysConfigs;
import cn.ilikes.tools.nosql.jpa.classloads.porxys.LazyInitializerFactory;
import cn.ilikes.tools.nosql.jpa.clients.handers.AbDataHander;
import cn.ilikes.tools.nosql.jpa.clients.handers.hbases.HBaseUtils;
import cn.ilikes.tools.nosql.jpa.clients.indexs.ABClientIndex;
import cn.ilikes.tools.nosql.jpa.graphs.Node;
import cn.ilikes.tools.nosql.jpa.graphs.NodeLifeCycle.LifeCycle;
import cn.ilikes.tools.nosql.jpa.metadatas.EntityMetaData;
import cn.ilikes.tools.nosql.jpa.metadatas.elements.EntityFields;
import cn.ilikes.tools.nosql.jpa.metadatas.elements.JPAField;
import cn.ilikes.tools.nosql.jpa.metadatas.elements.Relation;
import cn.ilikes.tools.nosql.jpa.unitls.JPAUtils;
import cn.ilikes.tools.nosql.jpa.unitls.PropertyAccessException;
import cn.ilikes.tools.nosql.jpa.unitls.PropertyAccessorHelper;

public class HbaseClient extends AbClient {

	private Logger logger = Loggerfactory.instance(HbaseClient.class);

	public HbaseClient(AbDataHander dataHander, ABClientIndex clientIndex, JPASQLPersistenUnitEnv persistenUnitEnv) {
		super(dataHander, clientIndex, persistenUnitEnv);
	}

	@Override
	public Node switchNode(EntityMetaData entityMetaData, Result result) throws JPASQLClientsException {
		if (result == null)
			return Node.NULL_NODE;
		return ResultToObject(entityMetaData, result);
	}

	private void relationJPAProxys(EntityFields entityFields, Result result, Object entity) throws JPASQLClientsException {
		JPASQLPersistenUnitEnv persistenUnitEnv = getPersistenUnitEnv();
		JPAField jPAField = entityFields.getjPAField();
		// one to many 
		if (PropertyAccessorHelper.isCollection(entityFields.getField().getType())) {
			try {
				Object va = null;
				if (PropertyAccessorHelper.isList(entityFields.getField().getType())) {
					LazyInitializerFactory lazyInitializerFactory = persistenUnitEnv.getSystemEnv().getLazyInitializerFactory();
					va = lazyInitializerFactory.getListProxy(this, entityFields, entity, persistenUnitEnv);
				} else {
					throw new JPASQLRunTimeException("this type  is not  list type ! ");
				}
				PropertyAccessorHelper.setFieldValue(entityFields.getField(), entity, va);
			} catch (PropertyAccessException e) {
				throw new JPASQLClientsException(e);
			}
		} else {
			String columnName = jPAField.getRelation().getColumnName();
			int index = columnName.indexOf(SysConfigs.hbase_column_family_qualifier);
			byte[] family = HBaseUtils.getBytes(JPAUtils.getfamily(columnName, index));
			byte[] qualifier = HBaseUtils.getBytes(JPAUtils.getQualifier(columnName, index));
			byte[] value = result.getValue(family, qualifier);
			if (value == null) {
				try {
					PropertyAccessorHelper.setFieldValue(entityFields.getField(), entity, value);
				} catch (PropertyAccessException e) {
					throw new JPASQLClientsException(e);
				}
			} else {
				Relation relation = entityFields.getjPAField().getRelation();
				EntityMetaData relationEntityMetaData = persistenUnitEnv.getMetaDataManagerFactory().selectIEntityMetaData(relation.getTargetEntity());

				LazyInitializerFactory lazyInitializerFactory = persistenUnitEnv.getSystemEnv().getLazyInitializerFactory();

				Object keyId = HBaseUtils.getByteTosObject(value, relationEntityMetaData.getEntityId().getField());

				Object proxy = lazyInitializerFactory.getProxy(entityFields, relationEntityMetaData, keyId, this.getAbstractContext());
				try {
					PropertyAccessorHelper.setFieldValue(entityFields.getField(), entity, proxy);
				} catch (PropertyAccessException e) {
					throw new JPASQLClientsException(e);
				}
			}
		}
	}

	public Node ResultToObject(EntityMetaData entityMetaData, Result result) throws JPASQLClientsException {
		try {
			Object object = PropertyAccessorHelper.instance(entityMetaData.getEntityClazz());
			Field fieldId = entityMetaData.getEntityId().getField();
			//id key   
			byte[] row = result.getRow();
			if (row == null)
				return Node.NULL_NODE;
			PropertyAccessorHelper.setFieldValue(fieldId, object, HBaseUtils.getPutByteTosObject(row, fieldId));
			Map<String, EntityFields> entityfields = entityMetaData.getEntityFields();
			for (Entry<String, EntityFields> entry : entityfields.entrySet()) {
				EntityFields entityFields = entry.getValue();
				if (entityFields.getEntityFieldsType().equals(EntityFields.EntityFieldsType.RoreignKey))
					continue;
				if (entityFields.getField().equals(fieldId))
					continue;
				JPAField jPAField = entityFields.getjPAField();
				//这里要处理
				if (jPAField.isRelation()) {
					relationJPAProxys(entityFields, result, object);
				} else {
					String columnName = jPAField.getColumnName();
					int index = columnName.indexOf(SysConfigs.hbase_column_family_qualifier);
					byte[] family = HBaseUtils.getBytes(JPAUtils.getfamily(columnName, index));
					byte[] qualifier = HBaseUtils.getBytes(JPAUtils.getQualifier(columnName, index));
					byte[] value = result.getValue(family, qualifier);
					PropertyAccessorHelper.setFieldValue(entityFields.getField(), object, HBaseUtils.getByteTosObject(value, entityFields.getField()));
				}
			}
			Node node = Node.createtNode(entityMetaData, object, LifeCycle.managed);
			return node;
		} catch (PropertyAccessException e) {
			throw new JPASQLClientsException(e);
		}
	}

}